package com.sansan.qiangji.aspect;

import com.sansan.qiangji.constant.RedisConstant;
import com.sansan.qiangji.exception.UserAuthorizeException;
import com.sansan.qiangji.utils.JWTUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class UserAuthorizeAspect {
    private StringRedisTemplate redisTemplate;

    @Autowired
    private void setRedisTemplate(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Pointcut("execution(public * com.sansan.qiangji.controller.*.*.*(..))" +
            "&& !execution(public * com.sansan.qiangji.controller.open.OpenController.*(..))" +
            "&& !execution(public * com.sansan.qiangji.controller.system.UserController.userLogin(..))")
    public void verify() {
    }

    @Before("verify()")
    public void doAuthorize() {
        log.info("【AOP】身份验证");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String accessToken = request.getHeader("accessToken");
        if (accessToken == null) {
            log.error("【AOP】accessToken为NULL");
            throw new UserAuthorizeException();
        }
        log.info("【AOP】accessToken: " + accessToken);
        String userInfo = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, accessToken));
        if (StringUtils.isEmpty(userInfo)) {
            log.error("【AOP】accessToken异常");
            throw new UserAuthorizeException();
        }
        Claims userInfoClaims = JWTUtil.checkJWT(userInfo);
        if (userInfoClaims == null) {
            log.error("【AOP】userInfo解密失败");
            throw new UserAuthorizeException();
        }
        String userName = userInfoClaims.get("userName", String.class);
        String loginTime = userInfoClaims.get("loginTime", String.class);
        String loginMethod = userInfoClaims.get("loginMethod", String.class);
        log.info("【AOP】用户：userName = {}, loginTime = {}, loginMethod = {}", userName, loginTime, loginMethod);
        request.setAttribute("userName", userName);
        request.setAttribute("loginTime", loginTime);
        request.setAttribute("loginMethod", loginMethod);
        if (request.getAttribute("loginMethod").equals("padLogin")) {
            String requestPath = request.getServletPath();
            if (!requestPath.split("/")[2].equals("pad")) {
                log.error("【AOP】accessToken没有接口权限");
                throw new UserAuthorizeException();
            }
        }
    }
}
